package com.fakesmoker.aidawnda.scoring;/**
 * @program: aidawnda-backend
 * @author: lcy
 * @create: 2024-11-09 16:27
 */

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fakesmoker.aidawnda.model.dto.question.QuestionContentDto;
import com.fakesmoker.aidawnda.model.entity.App;
import com.fakesmoker.aidawnda.model.entity.Question;
import com.fakesmoker.aidawnda.model.entity.ScoringResult;
import com.fakesmoker.aidawnda.model.entity.UserAnswer;
import com.fakesmoker.aidawnda.service.QuestionService;
import com.fakesmoker.aidawnda.service.ScoringResultService;
import com.fakesmoker.aidawnda.service.UserService;

import javax.annotation.Resource;
import java.util.List;

/**
 2024/11/9,
 */


/**
 * 自定义打分策略实现类
 * @author : lcy
 */

@ScoringStrategyConfigAnnotation(appType = 0,scoringStrategy = 0)
public class CustomScoreScoringStrategyImpl implements ScoringStrategy {

    @Resource
    private ScoringResultService scoringResultService;
    @Resource
    private QuestionService questionService;
    @Resource
    private UserService userService;

    @Override
    public UserAnswer doScore(List<String> choices, App app) {
        // 根据id查询到题目和题目结果信息 (按分数降序排序)
        Long appId = app.getId();
        Question question = questionService.getOne(Wrappers.lambdaQuery(Question.class)
                .eq(Question::getAppId, appId));
        List<ScoringResult> scoringResultList = scoringResultService.list(Wrappers.lambdaQuery(ScoringResult.class)
                .eq(ScoringResult::getAppId, appId)
                .orderByDesc(ScoringResult::getResultScoreRange));

        // 统计用户的总得分
        int totalScore = calculateTotalScore(choices, question);

        // 遍历得分结果，找到第一个用户分数大于得分范围的结果，作为最终结果
        ScoringResult finalResult = findFinalResult(scoringResultList, totalScore);

        // 构造返回值，填充答案对象属性
        UserAnswer userAnswer = new UserAnswer();

        userAnswer.setAppId(appId);
        userAnswer.setAppType(app.getAppType());
        userAnswer.setChoices(JSONUtil.toJsonStr(choices));
        userAnswer.setScoringStrategy(app.getScoringStrategy());
        userAnswer.setResultScore(totalScore);

        if (finalResult != null) {
            userAnswer.setResultId(finalResult.getId());
            userAnswer.setResultName(finalResult.getResultName());
            userAnswer.setResultDesc(finalResult.getResultDesc());
            userAnswer.setResultPicture(finalResult.getResultPicture());
        }

        return userAnswer;
    }

    @Override
    public UserAnswer doScoreBySingle(List<String> choices, App app) throws InterruptedException {
        return null;
    }

    /**
     * 计算用户的总得分。
     *
     * @param choices  用户的答题选择列表。
     * @param question 题目信息对象，用于获取题目内容以确定每道题目的分值等相关信息（此处假设题目内容包含分值信息，可根据实际情况调整）。
     * @return 返回用户的总得分。
     */
    private int calculateTotalScore(List<String> choices, Question question) {
        // 这里需要根据具体的题目内容和分值设定来计算用户的总得分
        // 例如，假设题目内容中每个选项对应一个固定分值，可通过解析题目内容获取每个选项的分值，然后根据用户选择累加得分
        // 以下是一个简单示例，假设题目内容的JSON格式已经解析为QuestionContentDto列表，且每个选项有一个分值属性"score"
        String questionContent = question.getQuestionContent();
        List<QuestionContentDto> questionContentDtoList = JSONUtil.toList(questionContent, QuestionContentDto.class);

        int totalScore = 0;
        for (int i = 0; i < choices.size(); i++) {
            String choice = choices.get(i);
            for (QuestionContentDto.Option option : questionContentDtoList.get(i).getOptions()) {
                if (option.getKey().equals(choice)) {
                    totalScore += option.getScore();
                }
            }
        }

        return totalScore;
    }

    /**
     * 在排序后的得分结果列表中，找到第一个用户分数大于得分范围的结果。
     *
     * @param scoringResultList 排序后的得分结果列表，按照得分范围降序排列。
     * @param totalScore        用户的总得分。
     * @return 返回符合条件的第一个得分结果对象，如果没有找到则返回null。
     */
    private ScoringResult findFinalResult(List<ScoringResult> scoringResultList, int totalScore) {
        for (ScoringResult scoringResult : scoringResultList) {
            if (totalScore >= scoringResult.getResultScoreRange()) {
                return scoringResult;
            }
        }
        return null;
    }
}